home *** CD-ROM | disk | FTP | other *** search
/ Alles Voor Internet / Tout Pour Internet / alles voor internet.iso / MacInternet™ / Modem / S&D III / Scanner.p < prev    next >
Encoding:
Text File  |  1993-06-30  |  38.1 KB  |  1,299 lines  |  [TEXT/PJMM]

  1. program Scanner;
  2.  
  3. {    This code was written in THINK Pascal 4 on a MacQuadra 950 - caches on too!                }
  4. {    You may use this code for whatever on the following conditions;                            }
  5. {        1.    You may not use it for any program (in whole or part) for you you will charge        }
  6. {        2.    You must include this code (with header & my details) when distributing            }
  7. {        3.    You must include the following message in your about box                            }
  8. {                                                                                                        }
  9. {                    'serial code by Boris (Boris@dylan.demon.co.uk)                                }
  10. {                                                                                                        }
  11. {        4.    You must feel really guilty if you don't send me a copy of your application            }
  12. {            (source code too would be nice...for my interest only, NOT to rip you off            }
  13. {                                                                                                        }
  14. {    Well, now onto the disclaimer bit...                                                                }
  15. {    I take no responsibility for any damage that this code may cause cuz it works fine        }
  16. {    for me and I've used it a lot with several applications running and it never did me            }
  17. {    any harm.  Use at your own risk, do regular exercise, always use a condom, be nice        }
  18. {    eat fruit, everybody knows what is meant in this bit and in a court of law I reckon        }
  19. {    its pretty bloody obvious what is meant by this bit so I'll shut my banter and leave        }
  20. {    you people to paw over this lovely piece of code where elegance is something that        }
  21. {    happens to other people (except MicroSoft! - dodgy is the keyword there).                    }
  22. {                                                                                                        }
  23. {    I don't expect any payment for this code.  It is free!!!  Give it to anyone!  Use it.            }
  24. {    Please don't rip off my code, or anyone else's, cuz that just makes you a sad bastard    .    }
  25. {    I put a lot of work into this, and I'm giving away many hours work to save you the        }
  26. {    effort.                                                                                                }
  27. {                                                                                                        }
  28. {    Feel free to mail me with any questions you have about this, or anything else.                }
  29. {    I reply to everything.                                                                            }
  30. {                                                                                                        }
  31. {    Boris@dylan.demon.co.uk  (IP. 158.152.11.47)                                                }
  32.  
  33.     uses
  34.         Serial;                            {include standard Serial.p library}
  35.  
  36.     const
  37.         ModemInput = '.AIn';            {driver name.  Use .BIn for printer port}
  38.         ModemOutput = '.AOut';        {driver name.  Use .BOut for printer port}
  39.  
  40.         myMenuBarID = 131;
  41.  
  42.         myAlertID = 128;
  43.         myPhoneNumberAlertID = 132;
  44.         myTimeErrorAlertID = 133;
  45.  
  46.         myAboutDialogID = 129;
  47.         myPhoneNumberDialogID = 130;
  48.         myPrefsDialogID = 131;
  49.  
  50.         myMainWindowID = 128;
  51.         myStatusWindowID = 129;
  52.  
  53.         myAboutMenuID = 128;
  54.         myFileMenuID = 129;
  55.         myOptionsMenuID = 130;
  56.  
  57.         delayTime = 180;        {3 second wait after dialing}
  58.         hangUpDelay = 120;        {2 second delay between +++ and ATH0}
  59.  
  60.  
  61.     type
  62.         StatusType = (idle, dialing, waiting, hangingUp);
  63.  
  64.     var
  65.         Active, Quit, Silent, BeepOnModem, BeepOnStart, BeepOnFinish, OffHook: boolean;
  66.         InShake, OutShake: SerShk;
  67.         Redials, ModemBaud, ModemStop, ModemParity, ModemData, ReceiveDriverRefNum, SendDriverRefNum: integer;
  68.         maxRedials, maxWaitTime, TotalModems, TotalBusy, TotalNoAnswer, TotalErrors, TotalCalls: integer;
  69.         Prefix: str255;
  70.         CurrentNumber, EndNumber, StartNumber, Timer: longint;
  71.         ResultsFilename, StartTime, StopTime: str255;
  72.         MenuBarHandle: handle;
  73.         SendBuffer, ReceiveBuffer: array[1..1000] of byte;
  74.         MainWindow: WindowPtr;
  75.         myEventRecord: EventRecord;
  76.         Status: StatusType;
  77.         myStopButton, myStartButton: ControlHandle;
  78.         StartButtonBox, StopButtonBox: rect;
  79.         ResultsFile: text;
  80.  
  81.     procedure doError (theError: integer);            {I prefer to have error strings and the like in the main code}
  82.         var                                                    {rather than storing then in string resources}
  83.             ErrorMessage, ErrorNumberString: str255;    {saves me having to have ResEdit open at the same time}
  84.     begin                                                    {I mean, I only have a 19" monitor}
  85.         case theError of
  86.             1: 
  87.                 ErrorMessage := 'The menu bar resources could not be found';
  88.             2: 
  89.                 ErrorMessage := 'Memory allocation for window storage failed';
  90.             3: 
  91.                 ErrorMessage := 'Unable to show ''About...'' dialog';
  92.             4: 
  93.                 ErrorMessage := 'Menu selection error';
  94.             5: 
  95.                 ErrorMessage := 'Unable to show ''Phone number...'' dialog';
  96.             6: 
  97.                 ErrorMessage := 'Unable to create controls';
  98.             7: 
  99.                 ErrorMessage := 'Failed to write to serial driver';
  100.             8: 
  101.                 ErrorMessage := 'Failed to read from serial driver';
  102.             9: 
  103.                 ErrorMessage := 'The phone is not connected or being used';
  104.             10: 
  105.                 ErrorMessage := 'An error occurred whilst opening the serial drivers';
  106.             11: 
  107.                 ErrorMessage := 'Failed to close serial drivers';
  108.             12: 
  109.                 ErrorMessage := 'Failed to create the results file';
  110.             13: 
  111.                 ErrorMessage := 'Failed to open the new results file';
  112.             14: 
  113.                 ErrorMessage := 'Failed to write to results file';
  114.             15: 
  115.                 ErrorMessage := 'Failed to close results file';
  116.             otherwise
  117.                 ErrorMessage := 'UNDEFINED ERROR';
  118.         end;
  119.         NumToString(theError, ErrorNumberString);
  120.         ParamText(ErrorNumberString, ErrorMessage, '', '');
  121.         theError := Alert(myAlertID, nil);
  122.     end;
  123.  
  124.     function StringCompare (String1, String2: str255): boolean;
  125.         var
  126.             loop: integer;
  127.     begin
  128.         StringCompare := EqualString(String1, String2, false, false);
  129.     end;
  130.  
  131. {-------------------------------------- Initialise -----------------------------------------}
  132.  
  133.     function SetupMenuBar: boolean;
  134.     begin
  135.         MenuBarHandle := GetNewMBar(myMenuBarID);
  136.         if MenuBarHandle = nil then
  137.             SetupMenuBar := false
  138.         else
  139.             begin
  140.                 HLock(MenuBarHandle);
  141.                 SetMenuBar(MenuBarHandle);
  142.                 SetMenuFlash(2);
  143.                 DrawMenuBar;
  144.                 SetupMenuBar := true;
  145.             end;
  146.     end;
  147.  
  148.     procedure KillMenuBar;
  149.     begin
  150.         if MenuBarHandle <> nil then
  151.             begin
  152.                 HUnlock(MenuBarHandle);
  153.                 DisposHandle(MenuBarHandle);
  154.             end;
  155.     end;
  156.  
  157.     function SetupWindows: boolean;
  158.     begin
  159.         MainWindow := GetNewWindow(myMainWindowID, nil, pointer(-1));
  160.         if MainWindow = nil then
  161.             SetupWindows := false                                                        {I do my own button drawing/handling}
  162.         else
  163.             begin
  164.                 myStartButton := NewControl(MainWindow, StartButtonBox, 'Start', true, 0, 0, 1, pushButProc, 1);
  165.                 myStopButton := NewControl(MainWindow, StopButtonBox, 'Stop', true, 0, 0, 1, pushButProc, 2);
  166.                 if (myStartButton = nil) or (myStopButton = nil) then
  167.                     begin
  168.                         doError(6);
  169.                         SetupWindows := false;
  170.                     end
  171.                 else
  172.                     begin
  173.                         HLock(handle(myStartButton));
  174.                         HLock(handle(myStopButton));
  175.                         SetupWindows := true;
  176.                     end;
  177.             end;
  178.     end;
  179.  
  180.     procedure KillWindows;
  181.     begin
  182.         if myStartButton <> nil then
  183.             begin
  184.                 HUnlock(handle(myStartButton));
  185.                 DisposeControl(myStartButton);
  186.             end;
  187.         if myStopButton <> nil then
  188.             begin
  189.                 HUnlock(handle(myStopButton));
  190.                 DisposeControl(myStopButton);
  191.             end;
  192.         if MainWindow <> nil then
  193.             DisposeWindow(MainWIndow);
  194.     end;
  195.  
  196.     procedure InitialiseVars;
  197.     begin
  198.         ModemBaud := baud2400;
  199.         ModemStop := stop10;
  200.         ModemParity := noParity;
  201.         ModemData := data8;
  202.         Prefix := '';
  203.         CurrentNumber := 0;
  204.         StartNumber := 0;
  205.         EndNumber := 0;
  206.         TotalModems := 0;
  207.         TotalBusy := 0;
  208.         TotalNoAnswer := 0;
  209.         TotalErrors := 0;
  210.         TotalCalls := 0;
  211.         BeepOnModem := true;
  212.         BeepOnStart := true;
  213.         BeepOnFinish := true;
  214.         OffHook := false;
  215.         StartTime := '00:00';
  216.         StopTime := '00:00';
  217.         ResultsFilename := 'Seek & Destroy III Results';
  218.         SetRect(StartButtonBox, 25, 220, 95, 240);
  219.         SetRect(StopButtonBox, 100, 220, 170, 240);
  220.         Redials := 0;
  221.         maxRedials := 3;
  222.         maxWaitTime := 30;
  223.         Silent := false;
  224.         Active := false;
  225.         Quit := false;
  226.     end;
  227.  
  228. {---------------------------------------- Serial setup ------------------------------------}
  229.     procedure CloseDrivers;
  230.         var
  231.             Error: OSErr;
  232.             problem: boolean;
  233.     begin
  234.         problem := false;
  235.         Error := CloseDriver(ReceiveDriverRefNum);
  236.         if Error <> noErr then
  237.             problem := true;
  238.         Error := CloseDriver(SendDriverRefNum);
  239.         if Error <> noErr then
  240.             problem := true;
  241.         if problem then
  242.             doError(11);                                                {••• These are pretty much the standard serial}
  243.     end;                                                                {routines I use for doing modemy type stuff}
  244.                                                                     {They're tried and tested and work well}
  245.     procedure SetupDrivers;
  246.         var
  247.             myErr: OSErr;
  248.             problem: boolean;
  249.     begin
  250.         problem := false;
  251.         myErr := OpenDriver(ModemInput, ReceiveDriverRefNum);                            {setup serial drivers}
  252.         if myErr <> noErr then
  253.             problem := true;
  254.         myErr := OpenDriver(ModemOutput, SendDriverRefNum);
  255.         if myErr <> noErr then
  256.             problem := true;
  257.         if not (problem) then
  258.             begin
  259.                 myErr := SerSetBuf(ReceiveDriverRefNum, @ReceiveBuffer, 4096);
  260.                 if myErr <> noErr then
  261.                     problem := true;
  262.                 myErr := SerSetBuf(SendDriverRefNum, @SendBuffer, 4096);
  263.                 if myErr <> noErr then
  264.                     problem := true;
  265.                 if not (problem) then
  266.                     begin
  267.                         myErr := SerReset(ReceiveDriverRefNum, ModemBaud + ModemStop + ModemParity + ModemData);
  268.                         if myErr <> noErr then
  269.                             problem := true;
  270.                         myErr := SerReset(SendDriverRefNum, ModemBaud + ModemStop + ModemParity + ModemData);
  271.                         if myErr <> noErr then
  272.                             problem := true;
  273.                         if not (problem) then
  274.                             begin
  275.                                 with InShake do    {Volume IV of SpInsideMac additions}
  276.                                     begin
  277.                                         fXOn := 0;  {XOn/XOff is off}
  278.                                         fCTS := 0;  {hardware CTS handshaking off}
  279.                                         xOn := chr(19);  {control-s}
  280.                                         xOff := chr(17);  {control-q}
  281.                                         errs := parityErr + hwOverrunErr + framingErr;  {busts if these errs happen}
  282.                                         evts := ctsEvent + breakEvent;  {sends driver events if these things happen}
  283.                                         fInX := 0;  {Xon/off input control flow flag}
  284.                                         fDtr := 0;  {useful}
  285.                                     end;
  286.                                 OutShake := InShake;
  287.                                 myErr := SerHShake(ReceiveDriverRefNum, InShake);
  288.                                 if myErr <> noErr then
  289.                                     problem := true;
  290.                                 myErr := SerHShake(SendDriverRefNum, OutShake);
  291.                                 if myErr <> noErr then
  292.                                     problem := true;
  293.                             end;
  294.                     end;
  295.             end;
  296.         if problem then
  297.             doError(10);
  298.     end;
  299.  
  300. {------------------------------------ Get from Serial port ------------------------------------------}
  301.  
  302.     procedure OutChar (TheChar: char);
  303.         var
  304.             StringLength: longint;
  305.             myErr: OSErr;
  306.     begin
  307.         StringLength := 1;
  308.         myErr := FSWrite(SendDriverRefNum, StringLength, ptr(ord(@TheChar) + 1));
  309.         if myErr <> noErr then
  310.             doError(7);
  311.     end;
  312.  
  313.     procedure OutString (TheString: str255);            {tacky way of doing it, but effective}
  314.         var                                                    {could just dump the whole string but this way I}
  315.             loop: integer;                                        {can detect the error at character level}
  316.     begin                                                    {rather than being told that the string couldn't be}
  317.         for loop := 1 to length(TheString) do                {sent...this way I know how far it got}
  318.             begin
  319.                 OutChar(TheString[loop]);                        {Anyway, I've been using this routine for years}
  320.             end;
  321.     end;
  322.  
  323.     procedure InChar (var TheChar: char);            {Get a char.  If none available then returns null chr(0)}
  324.         var
  325.             StringPtr: ptr;
  326.             StringLength: longint;
  327.             TheString: str255;
  328.             myErr: OSErr;
  329.     begin
  330.         myErr := SerGetBuf(ReceiveDriverRefNum, StringLength);
  331.         TheString := 'z';
  332.         if StringLength > 0 then
  333.             begin
  334.                 StringLength := 1;
  335.                 myErr := FSRead(ReceiveDriverRefNum, StringLength, ptr(ord(@TheString) + 1));
  336.                 TheChar := TheString[1];
  337.                 if myErr <> noErr then
  338.                     doError(8);
  339.             end
  340.         else
  341.             begin
  342.                 TheChar := chr(0);
  343.             end;
  344.     end;
  345.  
  346.     procedure InString (var TheString: str255);
  347.         var
  348.             StringPtr: ptr;
  349.             StringLength: longint;
  350.             TheChar: char;
  351.             myErr: OSErr;
  352.     begin
  353.         TheString := '';
  354.         TheChar := chr(0);
  355.         InChar(TheChar);
  356.         case TheChar of
  357.             'C':                                     {CONNECT message}
  358.                 begin
  359.                     StringLength := 6;
  360.                     myErr := FSRead(ReceiveDriverRefNum, StringLength, ptr(ord(@TheString) + 1));
  361.                     StringPtr := @TheString;
  362.                     StringPtr^ := StringLength;
  363.                 end;
  364.             'N':                                     {NO ANSWER message}
  365.                 begin
  366.                     StringLength := 9;
  367.                     myErr := FSRead(ReceiveDriverRefNum, StringLength, ptr(ord(@TheString) + 1));
  368.                     StringPtr := @TheString;
  369.                     StringPtr^ := StringLength;
  370.                 end;
  371.             'B':                                     {BUSY message}
  372.                 begin
  373.                     StringLength := 3;
  374.                     myErr := FSRead(ReceiveDriverRefNum, StringLength, ptr(ord(@TheString) + 1));
  375.                     StringPtr := @TheString;
  376.                     StringPtr^ := StringLength;
  377.                 end;
  378.             'E':                                     {ERROR message}
  379.                 begin
  380.                     StringLength := 4;
  381.                     myErr := FSRead(ReceiveDriverRefNum, StringLength, ptr(ord(@TheString) + 1));
  382.                     StringPtr := @TheString;
  383.                     StringPtr^ := StringLength;
  384.                 end;
  385.             otherwise
  386.                 begin
  387.                     TheString := 'dum dee doo';
  388.                 end;
  389.         end;
  390.     end;
  391.  
  392.     procedure ClearInputBuffer;
  393.         var
  394.             DummyChar: char;
  395.     begin
  396.         DummyChar := 'a';
  397.         while DummyChar <> chr(0) do        {Not th best way to do this...better off reading until}
  398.             begin                                    {buffer length is zero...so far, though, its worked fine}
  399.                 InChar(DummyChar);                    {and its been used a lot}
  400.             end;
  401.     end;
  402.  
  403. {--------------------------------------- Draw Screen ------------------------------------------}
  404.  
  405.     procedure DrawInfo (Heading, info: str255);
  406.     begin
  407.         TextFace([bold]);
  408.         DrawString(Heading);
  409.         TextFace([]);
  410.         DrawString(info);
  411.     end;
  412.  
  413.     function CleanNumber (theNum: longint): str255;        {strips off leading spaces}
  414.         var
  415.             theString: str255;
  416.     begin
  417.         NumToString(theNum, theString);
  418.         while theString[1] = ' ' do
  419.             delete(theString, 1, 1);
  420.         CleanNumber := theString;
  421.     end;
  422.  
  423.     procedure DrawMainWindow;
  424.         var
  425.             tempString: str255;
  426.     begin
  427.         SetPort(MainWindow);
  428.         SelectWindow(MainWindow);
  429.         EraseRect(MainWindow^.portRect);
  430.         MoveTo(10, 25);
  431.         TextFace([Bold] + [outline]);
  432.         TextFont(helvetica);
  433.         TextSize(24);
  434.         DrawString('BorMak Tech');
  435.         MoveTo(15, 47);
  436.         TextFace([Bold]);
  437.         TextFont(times);
  438.         TextSize(18);
  439.         DrawString('  Seek & Destroy III');
  440.         MoveTo(10, 70);
  441.         TextFace([bold]);
  442.         TextFont(geneva);
  443.         TextSize(9);
  444.         case Status of
  445.             idle: 
  446.                 DrawInfo('Status:', 'Idle');
  447.             dialing: 
  448.                 DrawInfo('Status:', 'Dialing...');
  449.             waiting: 
  450.                 DrawInfo('Status:', 'Waiting...');
  451.             hangingUp: 
  452.                 DrawInfo('Status:', 'Hanging up...');
  453.             otherwise
  454.                 DrawInfo('Error', '');
  455.         end;
  456.         MoveTo(10, 85);
  457.         TempString := CleanNumber(CurrentNumber);
  458.         DrawInfo('Number:', concat('   ', Prefix, '  ', TempString));
  459.         MoveTo(10, 100);
  460.         TempString := CleanNumber(TotalModems);
  461.         DrawInfo('Modems:', TempString);
  462.         MoveTo(10, 115);
  463.         TempString := CleanNumber(TotalBusy);
  464.         DrawInfo('Busy:', TempString);
  465.         MoveTo(10, 130);
  466.         TempString := CleanNumber(TotalNoAnswer);
  467.         DrawInfo('No answer:', TempString);
  468.         MoveTo(10, 145);
  469.         TempString := CleanNumber(TotalErrors);
  470.         DrawInfo('Errors:', TempString);
  471.         MoveTo(10, 160);
  472.         TempString := CleanNumber(TotalCalls);
  473.         DrawInfo('Calls:', TempString);
  474.         MoveTo(10, 180);
  475.         DrawInfo('Start time:', StartTime);
  476.         MoveTo(10, 195);
  477.         DrawInfo('Stop time:', StopTime);
  478.         DrawControls(MainWindow);
  479.         MoveTo(370, 245);
  480.         DrawInfo('', 'Boris');                    {leave this in, please...give me SOME credit!}
  481.     end;
  482.  
  483.     procedure ShowAboutWindow;            {Don't forget...if you use any of my code, include my name&address}
  484.         var                                        {in your about box}
  485.             MyDialogPtr: DialogPtr;
  486.             TheItem: integer;
  487.     begin
  488.         MyDialogPtr := GetNewDialog(myAboutDialogID, nil, pointer(-1));
  489.         if MyDialogPtr = nil then
  490.             doError(3)
  491.         else
  492.             begin
  493.                 ModalDialog(nil, TheItem);
  494.                 DisposDialog(MyDialogPtr);
  495.             end;
  496.     end;
  497.  
  498. {------------------------------- Selections ---------------------------}
  499.     procedure DumpToFile (messageString: str255);
  500.         var
  501.             tempString, timeString, dateString: str255;
  502.             currentTime: longint;
  503.     begin
  504.         GetDateTime(currentTime);
  505.         IUTimeString(currentTime, true, timeString);
  506.         IUDateString(currentTime, longDate, dateString);
  507.         NumToString(currentNumber, tempString);
  508.         writeln(ResultsFile, messageString, '    ', Prefix, '  ', tempString, '    ', timeString, ' on ', dateString);
  509.     end;
  510.  
  511.     procedure OpenResultsFile (theFilename: str255);        {Could always do it properly but using the}
  512.     begin                                                            {standard pascal commands is Sooooooo much easier}
  513.         Rewrite(ResultsFile, theFilename);
  514.     end;
  515.  
  516.     procedure CloseResultFile;
  517.         var
  518.             tempString, timeString, dateString: str255;
  519.             currentTime: longint;
  520.     begin
  521.         GetDateTime(currentTime);
  522.         IUTimeString(currentTime, true, timeString);
  523.         IUDateString(currentTime, longDate, dateString);
  524.         writeln(ResultsFile, '');
  525.         writeln(ResultsFile, '========================================================');
  526.         writeln(ResultsFile, 'Result file closed at ', timeString, ' on ', dateString);
  527.         NumToString(currentNumber, tempString);
  528.         writeln(ResultsFile, 'Current number:', Prefix, '  ', tempString);
  529.         Close(ResultsFile);
  530.     end;
  531.  
  532.     procedure DumpHeader;
  533.         var
  534.             timeString, dateString: str255;
  535.             currentTime: longint;
  536.     begin
  537.         GetDateTime(currentTime);
  538.         IUTimeString(currentTime, true, timeString);
  539.         IUDateString(currentTime, longDate, dateString);
  540.         writeln(ResultsFile, 'BorMak Tech  Seek & Destroy III Results File');
  541.         writeln(ResultsFile, 'Results file created at ', timeString, ' on ', dateString);
  542.         writeln(ResultsFile, '========================================================');
  543.         writeln(ResultsFile, '');
  544.     end;
  545.  
  546.     function GetFilename (closeFirst: boolean): boolean;
  547.     begin
  548.         ResultsFilename := newfilename('Put results where?', 'Seek & Destroy III Results');
  549.         if ResultsFilename = '' then
  550.             GetFilename := false
  551.         else
  552.             begin
  553.                 if closeFirst then
  554.                     CloseResultFile;
  555.                 rewrite(ResultsFile, ResultsFilename);
  556.                 DumpHeader;
  557.                 GetFilename := true;
  558.             end;
  559.     end;
  560.  
  561.     procedure SelectPhoneNumber;
  562.         var
  563.             myDialog: DialogPtr;
  564.             finished: boolean;
  565.             itemHandle: handle;
  566.             tempString: str255;
  567.             itemRect: rect;
  568.             itemType, theItem: integer;
  569.             newNumber: longint;
  570.     begin
  571.         myDialog := GetNewDialog(myPhoneNumberDialogID, nil, pointer(-1));
  572.         if myDialog = nil then
  573.             doError(5)
  574.         else
  575.             begin
  576.                 NumToString(currentNumber, tempString);
  577.                 GetDItem(myDialog, 4, itemType, itemHandle, itemRect);
  578.                 SetIText(itemHandle, tempString);
  579.                 GetDItem(myDialog, 3, itemType, itemHandle, itemRect);
  580.                 SetIText(itemHandle, Prefix);
  581.                 DrawDialog(myDialog);
  582.                 finished := false;
  583.                 while not (finished) do
  584.                     begin
  585.                         ModalDialog(nil, theItem);
  586.                         if theItem = 1 then
  587.                             begin
  588.                                 GetDItem(myDialog, 4, itemType, itemHandle, itemRect);
  589.                                 GetIText(itemHandle, tempString);
  590.                                 StringToNum(tempString, newNumber);
  591.                                 if newNumber < 0 then
  592.                                     begin
  593.                                         theItem := Alert(myPhoneNumberAlertID, nil);
  594.                                         SelIText(myDialog, 4, 0, 255);
  595.                                     end
  596.                                 else
  597.                                     begin
  598.                                         GetDItem(myDialog, 4, itemType, itemHandle, itemRect);
  599.                                         GetIText(itemHandle, tempString);
  600.                                         StringToNum(tempString, newNumber);
  601.                                         GetDItem(myDialog, 3, itemType, itemHandle, itemRect);
  602.                                         GetIText(itemHandle, Prefix);
  603.                                         finished := true;
  604.                                     end;
  605.                             end
  606.                         else if theItem = 2 then
  607.                             Finished := true;
  608.                     end;
  609.                 CurrentNumber := newNumber;
  610.                 DisposDialog(myDialog);
  611.             end;
  612.     end;
  613.  
  614.     function TimeValid (theTime: str255): boolean;
  615.         var
  616.             Result: boolean;
  617.             tempString: str255;                            {this routine is TACKY but works}
  618.             tempNum: longint;
  619.     begin
  620.         Result := true;
  621.         if length(theTime) <> 5 then
  622.             Result := false
  623.         else if theTime[3] <> ':' then
  624.             Result := false
  625.         else
  626.             begin
  627.                 tempString := copy(theTime, 1, 2);
  628.                 StringToNum(tempString, tempNum);
  629.                 if (tempNum < 0) or (tempNum > 23) then
  630.                     Result := false
  631.                 else
  632.                     begin
  633.                         tempString := copy(theTime, 4, 2);
  634.                         StringToNum(tempString, tempNum);
  635.                         if (tempNum < 0) or (TempNum > 59) then
  636.                             Result := false;
  637.                     end;
  638.             end;
  639.         TimeValid := Result;
  640.     end;
  641.  
  642.     function GetSelectedControl (theDialog: dialogPtr; first, last: integer): integer;
  643.         var
  644.             loop, theType: integer;
  645.             itemRect: rect;
  646.             itemHandle: handle;
  647.             gottit: boolean;
  648.     begin
  649.         loop := first - 1;
  650.         gottit := false;
  651.         repeat
  652.             loop := loop + 1;
  653.             GetDItem(theDialog, loop, theType, itemHandle, itemRect);
  654.             if GetCtlValue(ControlHandle(itemHandle)) > 0 then
  655.                 gottit := true;
  656.         until (GetCtlValue(ControlHandle(itemHandle)) > 0) or (loop = last);
  657.         if gottit then
  658.             GetSelectedControl := loop
  659.         else
  660.             GetSelectedControl := 0;
  661.     end;
  662.  
  663.     procedure SelectPrefs;                    {there HAS to be a better way of doing this stuff}
  664.         var                                        {so far it eludes me but I'm happy doing it like this for the moment}
  665.             myDialog: dialogPtr;
  666.             loop, theItem, theType: integer;
  667.             tempLong: longint;
  668.             itemRect: rect;
  669.             itemHandle: handle;
  670.             finished: boolean;
  671.             theEvent: eventRecord;
  672.             tempString: str255;
  673.     begin
  674.         myDialog := GetNewDialog(myPrefsDialogID, nil, pointer(-1));
  675.         if myDialog = nil then
  676.             doError(5)
  677.         else
  678.             begin
  679.                 for loop := 3 to 26 do
  680.                     begin
  681.                         GetDItem(myDialog, loop, theType, itemHandle, itemRect);
  682.                         SetCtlValue(ControlHandle(itemHandle), 0);
  683.                     end;
  684.                 case ModemBaud of
  685.                     baud300: 
  686.                         theItem := 13;
  687.                     baud600: 
  688.                         theItem := 12;
  689.                     baud1200: 
  690.                         theItem := 11;
  691.                     baud1800: 
  692.                         theItem := 10;
  693.                     baud2400: 
  694.                         theItem := 9;
  695.                     baud3600: 
  696.                         theItem := 8;
  697.                     baud4800: 
  698.                         theItem := 7;
  699.                     baud7200: 
  700.                         theItem := 6;
  701.                     baud9600: 
  702.                         theItem := 5;
  703.                     baud19200: 
  704.                         theItem := 4;
  705.                     baud57600: 
  706.                         theItem := 3;
  707.                     otherwise
  708.                         theItem := 3;
  709.                 end;
  710.                 GetDItem(myDialog, theItem, theType, itemHandle, itemRect);
  711.                 SetCtlValue(ControlHandle(itemHandle), 1);
  712.                 case ModemStop of
  713.                     stop10: 
  714.                         theItem := 14;
  715.                     stop20: 
  716.                         theItem := 16;
  717.                     otherwise
  718.                         theItem := 15;    {stop15 - invalid for case statement value= -32768}
  719.                 end;
  720.                 GetDItem(myDialog, theItem, theType, itemHandle, itemRect);
  721.                 SetCtlValue(ControlHandle(itemHandle), 1);
  722.                 case ModemParity of
  723.                     noParity: 
  724.                         theItem := 17;
  725.                     oddParity: 
  726.                         theItem := 18;
  727.                     evenParity: 
  728.                         theItem := 19;
  729.                     otherwise
  730.                         theItem := 17;
  731.                 end;
  732.                 GetDItem(myDialog, theItem, theType, itemHandle, itemRect);
  733.                 SetCtlValue(ControlHandle(itemHandle), 1);
  734.                 case ModemData of
  735.                     0: 
  736.                         theItem := 20;
  737.                     2048: 
  738.                         theItem := 21;
  739.                     1024: 
  740.                         theItem := 22;
  741.                     3072: 
  742.                         theItem := 23;
  743.                     otherwise
  744.                         theItem := 23;
  745.                 end;
  746.                 GetDItem(myDialog, theItem, theType, itemHandle, itemRect);
  747.                 SetCtlValue(ControlHandle(itemHandle), 1);
  748.                 if BeepOnModem then
  749.                     begin
  750.                         GetDItem(myDialog, 24, theType, itemHandle, itemRect);
  751.                         SetCtlValue(ControlHandle(itemHandle), 1);
  752.                     end;
  753.                 if BeepOnStart then
  754.                     begin
  755.                         GetDItem(myDialog, 25, theType, itemHandle, itemRect);
  756.                         SetCtlValue(ControlHandle(itemHandle), 1);
  757.                     end;
  758.                 if BeepOnFinish then
  759.                     begin
  760.                         GetDItem(myDialog, 26, theType, itemHandle, itemRect);
  761.                         SetCtlValue(ControlHandle(itemHandle), 1);
  762.                     end;
  763.                 GetDItem(myDialog, 40, theType, itemHandle, itemRect);
  764.                 if Silent then
  765.                     SetCtlValue(ControlHandle(itemHandle), 1)
  766.                 else
  767.                     SetCtlValue(ControlHandle(itemHandle), 0);
  768.                 GetDItem(myDialog, 27, theType, itemHandle, itemRect);
  769.                 SetIText(itemHandle, StartTime);
  770.                 GetDItem(myDialog, 28, theType, itemHandle, itemRect);
  771.                 SetIText(itemHandle, StopTime);
  772.                 NumToString(maxRedials, tempString);
  773.                 GetDItem(myDialog, 37, theType, itemHandle, itemRect);
  774.                 SetIText(itemHandle, tempString);
  775.                 NumToString(maxWaitTime, tempString);
  776.                 GetDItem(myDialog, 39, theType, itemHandle, itemRect);
  777.                 SetIText(itemHandle, tempString);
  778.                 DrawDialog(myDialog);
  779.                 finished := false;
  780.                 while not (finished) do
  781.                     begin
  782.                         repeat
  783.                         until GetNextEvent(everyEvent, theEvent);
  784.                         if IsDialogEvent(theEvent) then
  785.                             if DialogSelect(theEvent, myDialog, theItem) then
  786.                                 begin
  787.                                     case theItem of
  788.                                         1: 
  789.                                             begin
  790.                                                 GetDItem(myDialog, 27, theType, itemHandle, itemRect);
  791.                                                 GetIText(itemHandle, tempString);
  792.                                                 if not (TimeValid(tempString)) then
  793.                                                     begin
  794.                                                         loop := Alert(myTimeErrorAlertID, nil);
  795.                                                         SelIText(myDialog, 27, 0, 255);
  796.                                                     end
  797.                                                 else
  798.                                                     begin
  799.                                                         GetDItem(myDialog, 28, theType, itemHandle, itemRect);
  800.                                                         GetIText(itemHandle, tempString);
  801.                                                         if not (TimeValid(tempString)) then
  802.                                                             begin
  803.                                                                 loop := Alert(myTimeErrorAlertID, nil);
  804.                                                                 SelIText(myDialog, 28, 0, 255);
  805.                                                             end
  806.                                                         else
  807.                                                             begin
  808.                                                                 theItem := GetSelectedControl(myDialog, 3, 13);
  809.                                                                 case theItem of
  810.                                                                     3: 
  811.                                                                         ModemBaud := baud57600;
  812.                                                                     4: 
  813.                                                                         ModemBaud := baud19200;
  814.                                                                     5: 
  815.                                                                         ModemBaud := baud9600;
  816.                                                                     6: 
  817.                                                                         ModemBaud := baud7200;
  818.                                                                     7: 
  819.                                                                         ModemBaud := baud4800;
  820.                                                                     8: 
  821.                                                                         ModemBaud := baud3600;
  822.                                                                     9: 
  823.                                                                         ModemBaud := baud2400;
  824.                                                                     10: 
  825.                                                                         ModemBaud := baud1800;
  826.                                                                     11: 
  827.                                                                         ModemBaud := baud1200;
  828.                                                                     12: 
  829.                                                                         ModemBaud := baud600;
  830.                                                                     13: 
  831.                                                                         ModemBaud := baud300;
  832.                                                                     otherwise
  833.                                                                 end;
  834.                                                                 theItem := GetSelectedControl(myDialog, 14, 16);
  835.                                                                 case theItem of
  836.                                                                     14: 
  837.                                                                         ModemStop := stop10;
  838.                                                                     15: 
  839.                                                                         ModemStop := stop15;
  840.                                                                     16: 
  841.                                                                         ModemStop := stop20;
  842.                                                                     otherwise
  843.                                                                 end;
  844.                                                                 theItem := GetSelectedControl(myDialog, 17, 19);
  845.                                                                 case theItem of
  846.                                                                     17: 
  847.                                                                         ModemParity := noParity;
  848.                                                                     18: 
  849.                                                                         ModemParity := oddParity;
  850.                                                                     19: 
  851.                                                                         ModemParity := evenParity;
  852.                                                                     otherwise
  853.                                                                 end;
  854.                                                                 theItem := GetSelectedControl(myDialog, 20, 23);
  855.                                                                 case theItem of
  856.                                                                     20: 
  857.                                                                         ModemData := data5;
  858.                                                                     21: 
  859.                                                                         ModemData := data6;
  860.                                                                     22: 
  861.                                                                         ModemData := data7;
  862.                                                                     23: 
  863.                                                                         ModemData := data8;
  864.                                                                     otherwise
  865.                                                                 end;
  866.                                                                 GetDItem(myDialog, 24, theType, itemHandle, itemRect);
  867.                                                                 if GetCtlValue(ControlHandle(itemHandle)) > 0 then
  868.                                                                     BeepOnModem := true
  869.                                                                 else
  870.                                                                     BeepOnModem := false;
  871.                                                                 GetDItem(myDialog, 25, theType, itemHandle, itemRect);
  872.                                                                 if GetCtlValue(ControlHandle(itemHandle)) > 0 then
  873.                                                                     BeepOnStart := true
  874.                                                                 else
  875.                                                                     BeepOnStart := false;
  876.                                                                 GetDItem(myDialog, 26, theType, itemHandle, itemRect);
  877.                                                                 if GetCtlValue(ControlHandle(itemHandle)) > 0 then
  878.                                                                     BeepOnFinish := true
  879.                                                                 else
  880.                                                                     BeepOnFinish := false;
  881.                                                                 GetDItem(myDialog, 40, theType, itemHandle, itemRect);
  882.                                                                 if GetCtlValue(ControlHandle(itemHandle)) > 0 then
  883.                                                                     Silent := true
  884.                                                                 else
  885.                                                                     Silent := false;
  886.                                                                 GetDItem(myDialog, 27, theType, itemHandle, itemRect);
  887.                                                                 GetIText(itemHandle, StartTime);
  888.                                                                 GetDItem(myDialog, 28, theType, itemHandle, itemRect);
  889.                                                                 GetIText(itemHandle, StopTime);
  890.                                                                 GetDItem(myDialog, 37, theType, itemHandle, itemRect);
  891.                                                                 GetIText(itemHandle, tempString);
  892.                                                                 StringToNum(tempString, tempLong);
  893.                                                                 maxRedials := LoWord(tempLong);
  894.                                                                 GetDItem(myDialog, 39, theType, itemHandle, itemRect);
  895.                                                                 GetIText(itemHandle, tempString);
  896.                                                                 StringToNum(tempString, tempLong);
  897.                                                                 maxWaitTime := LoWord(tempLong);
  898.                                                                 CloseDrivers;
  899.                                                                 SetupDrivers;
  900.                                                                 finished := true;
  901.                                                             end;
  902.                                                     end;
  903.                                             end;
  904.                                         2: 
  905.                                             finished := true;
  906.                                         3..13: 
  907.                                             begin
  908.                                                 for loop := 3 to 13 do
  909.                                                     begin
  910.                                                         GetDItem(myDialog, loop, theType, itemHandle, itemRect);
  911.                                                         SetCtlValue(ControlHandle(itemHandle), 0);
  912.                                                     end;
  913.                                                 GetDItem(myDialog, theItem, theType, itemHandle, itemRect);
  914.                                                 SetCtlValue(ControlHandle(itemHandle), 1);
  915.                                             end;
  916.                                         14..16: 
  917.                                             begin
  918.                                                 for loop := 14 to 16 do
  919.                                                     begin
  920.                                                         GetDItem(myDialog, loop, theType, itemHandle, itemRect);
  921.                                                         SetCtlValue(ControlHandle(itemHandle), 0);
  922.                                                     end;
  923.                                                 GetDItem(myDialog, theItem, theType, itemHandle, itemRect);
  924.                                                 SetCtlValue(ControlHandle(itemHandle), 1);
  925.                                             end;
  926.                                         17..19: 
  927.                                             begin
  928.                                                 for loop := 17 to 19 do
  929.                                                     begin
  930.                                                         GetDItem(myDialog, loop, theType, itemHandle, itemRect);
  931.                                                         SetCtlValue(ControlHandle(itemHandle), 0);
  932.                                                     end;
  933.                                                 GetDItem(myDialog, theItem, theType, itemHandle, itemRect);
  934.                                                 SetCtlValue(ControlHandle(itemHandle), 1);
  935.                                             end;
  936.                                         20..23: 
  937.                                             begin
  938.                                                 for loop := 20 to 23 do
  939.                                                     begin
  940.                                                         GetDItem(myDialog, loop, theType, itemHandle, itemRect);
  941.                                                         SetCtlValue(ControlHandle(itemHandle), 0);
  942.                                                     end;
  943.                                                 GetDItem(myDialog, theItem, theType, itemHandle, itemRect);
  944.                                                 SetCtlValue(ControlHandle(itemHandle), 1);
  945.                                             end;
  946.                                         24..26: 
  947.                                             begin
  948.                                                 GetDItem(myDialog, theItem, theType, itemHandle, itemRect);
  949.                                                 if GetCtlValue(ControlHandle(itemHandle)) > 0 then
  950.                                                     loop := 0
  951.                                                 else
  952.                                                     loop := 1;
  953.                                                 SetCtlValue(ControlHandle(itemHandle), loop);
  954.                                             end;
  955.                                         40: 
  956.                                             begin
  957.                                                 GetDItem(myDialog, theItem, theType, itemHandle, itemRect);
  958.                                                 if GetCtlValue(ControlHandle(itemHandle)) > 0 then
  959.                                                     loop := 0
  960.                                                 else
  961.                                                     loop := 1;
  962.                                                 SetCtlValue(ControlHandle(itemHandle), loop);
  963.                                             end;
  964.                                         otherwise
  965.                                     end;
  966.                                 end;
  967.                     end;
  968.                 DisposDialog(myDialog);                    {phew!  Long routine to do something so simple}
  969.             end;
  970.     end;
  971.  
  972.     procedure HangUp;                            {last time I wrote this routine I just closed the drivers}
  973.         var                                            {then opened them again.  Works very well!}
  974.             dummy: longint;                            {Thought I'd be cleaner this time}
  975.     begin                                            {I did find, however, that the Teleport modem didn't work well}
  976.         if OffHook then                                {with this ATH business...dunno why}
  977.             begin
  978.                 Status := hangingUp;
  979.                 DrawMainWindow;
  980.                 OutString('+++');
  981.                 Delay(hangUpDelay, dummy);
  982.                 OutString(concat('ATZ', chr(13)));
  983.                 Delay(hangUpDelay, dummy);
  984.                 OutString(concat('ATH', chr(13)));
  985.                 CloseDrivers;
  986.                 SetupDrivers;
  987.                 ClearInputBuffer;
  988.             end;
  989.         OffHook := false;
  990.     end;
  991.  
  992.     procedure CheckTimer;
  993.         var
  994.             CurrentTime: longint;
  995.             tempString: str255;
  996.     begin
  997.         if not (EqualString(StartTime, StopTime, false, false)) then
  998.             begin
  999.                 GetDateTime(CurrentTime);
  1000.                 IUTimeString(currentTime, false, tempString);
  1001.                 if Active then
  1002.                     begin
  1003.                         if EqualString(tempString, StopTime, false, false) then
  1004.                             if Status = dialing then
  1005.                                 begin
  1006.                                     Active := false;
  1007.                                     if BeepOnFinish then
  1008.                                         SysBeep(1);
  1009.                                     HangUp;
  1010.                                     Status := idle;
  1011.                                     DrawMainWindow;
  1012.                                 end;
  1013.                     end
  1014.                 else
  1015.                     begin
  1016.                         if EqualString(tempString, StartTime, false, false) then
  1017.                             begin
  1018.                                 Status := dialing;
  1019.                                 DrawMainWindow;
  1020.                                 if BeepOnStart then
  1021.                                     SysBeep(1);
  1022.                                 Active := true;
  1023.                             end;
  1024.                     end
  1025.             end;
  1026.     end;
  1027.  
  1028.     procedure DialNumber;
  1029.         var
  1030.             tempString: str255;
  1031.             dummy: longint;
  1032.     begin
  1033.         OffHook := true;
  1034.         NumToString(currentNumber, tempString);
  1035.         ClearInputBuffer;
  1036.         OutString(concat('ATZ', chr(13)));
  1037.         Delay(60, dummy);
  1038.         if Silent then
  1039.             OutString(concat('ATM0', chr(13)))                {turns the modem speaker off if it has one}
  1040.         else
  1041.             OutString(concat('ATM2', chr(13)));
  1042.         Delay(60, dummy);
  1043.         OutString(concat('ATDT ', prefix, tempString, chr(13)));
  1044.         Delay(delayTime, dummy);
  1045.         TotalCalls := TotalCalls + 1;
  1046.         Status := waiting;
  1047.         DrawMainWindow;
  1048.         GetDateTime(Timer);
  1049.     end;
  1050.  
  1051.     procedure NextNumber;
  1052.     begin
  1053.         HangUp;
  1054.         currentNumber := currentNumber + 1;
  1055.         Status := dialing;
  1056.         DrawMainWindow;
  1057.     end;
  1058.  
  1059.     function TimedOut: boolean;
  1060.         var
  1061.             timeNow: longint;
  1062.     begin
  1063.         GetDateTime(timeNow);
  1064.         if timeNow - Timer > maxWaitTime then
  1065.             TimedOut := true
  1066.         else
  1067.             TimedOut := false;
  1068.     end;
  1069.  
  1070.     procedure DoSerial;
  1071.         var
  1072.             fromModem: str255;
  1073.     begin
  1074.         if not (TimedOut) then
  1075.             begin
  1076.                 InString(fromModem);
  1077.                 if StringCompare(fromModem, 'ONNECT') = true then
  1078.                     begin
  1079.                         TotalModems := TotalModems + 1;
  1080.                         if BeepOnModem then
  1081.                             SysBeep(1);
  1082.                         DumpToFile('Modem found');
  1083.                         NextNumber;
  1084.                     end
  1085.                 else if StringCompare(fromModem, 'O CARRIER') = true then
  1086.                     begin
  1087.                         NextNumber;
  1088.                     end
  1089.                 else if StringCompare(fromModem, 'O ANSWER') = true then
  1090.                     begin
  1091.                         TotalNoAnswer := TotalNoAnswer + 1;
  1092.                         DumpToFile('No answer');
  1093.                         NextNumber;
  1094.                     end
  1095.                 else if StringCompare(fromModem, 'USY') = true then
  1096.                     begin
  1097.                         HangUp;
  1098.                         Redials := Redials + 1;
  1099.                         if Redials > MaxRedials then
  1100.                             begin
  1101.                                 Redials := 0;
  1102.                                 TotalBusy := TotalBusy + 1;
  1103.                                 DumpToFile('Number busy');
  1104.                                 NextNumber;
  1105.                             end;
  1106.                         Status := dialing;
  1107.                         DrawMainWindow;
  1108.                     end
  1109.                 else if StringCompare(fromModem, 'O DIALTON') = true then
  1110.                     begin
  1111.                         HangUp;
  1112.                         doError(9);
  1113.                         Status := dialing;
  1114.                         DrawMainWindow;
  1115.                     end
  1116.                 else if StringCompare(fromModem, 'RROR') = true then
  1117.                     begin
  1118.                         TotalErrors := TotalErrors + 1;
  1119.                         DumpToFile('Error');
  1120.                         NextNumber;
  1121.                     end;
  1122.             end
  1123.         else
  1124.             begin
  1125.                 HangUp;
  1126.                 TotalNoAnswer := TotalNoAnswer + 1;
  1127.                 NextNumber;
  1128.             end;
  1129.     end;
  1130.  
  1131. {------------------------------- Menus & Keys ------------------------}
  1132.     procedure DoMenuSelection (MousePosition: Point);
  1133.         var
  1134.             MenuSelection: longint;
  1135.             MenuID, MenuItem: integer;
  1136.             dummy: boolean;
  1137.     begin
  1138.         MenuSelection := MenuSelect(MousePosition);
  1139.         MenuID := HiWord(MenuSelection);
  1140.         MenuItem := LoWord(MenuSelection);
  1141.         case MenuID of
  1142.             myAboutMenuID: 
  1143.                 if MenuItem = 1 then
  1144.                     ShowAboutWindow;
  1145.             myFileMenuID: 
  1146.                 if MenuItem = 1 then
  1147.                     dummy := GetFilename(true)
  1148.                 else if MenuItem = 2 then
  1149.                     Quit := true
  1150.                 else
  1151.                     doError(4);
  1152.             myOptionsMenuID: 
  1153.                 if MenuItem = 1 then
  1154.                     SelectPhoneNumber
  1155.                 else if MenuItem = 2 then
  1156.                     SelectPrefs
  1157.                 else
  1158.                     doError(4);
  1159.             otherwise
  1160.         end;
  1161.         HiliteMenu(0);
  1162.     end;
  1163.  
  1164.     procedure DoKeyEvent (TheKey: char);
  1165.     begin
  1166.         case TheKey of
  1167.             'q', 'Q': 
  1168.                 Quit := true;
  1169.             otherwise
  1170.         end;
  1171.         HiliteMenu(0);
  1172.     end;
  1173.  
  1174.     procedure DoMouseEvent (theEvent: EventRecord);
  1175.         var
  1176.             MouseWhere: integer;
  1177.             WindowSelected: WindowPtr;
  1178.             tempPt: point;
  1179.     begin
  1180.         MouseWhere := FindWindow(theEvent.where, WindowSelected);
  1181.         case MouseWhere of
  1182.             inMenuBar: 
  1183.                 DoMenuSelection(theEvent.where);
  1184.             inGoAway: 
  1185.                 if WindowSelected = MainWindow then
  1186.                     if TrackGoAway(MainWindow, theEvent.where) then
  1187.                         Quit := true;
  1188.             inDrag: 
  1189.                 DragWindow(MainWindow, theEvent.where, screenbits.bounds);
  1190.             inGrow, inContent: 
  1191.                 begin
  1192.                     tempPt := theEvent.where;
  1193.                     GlobalToLocal(tempPt);
  1194.                     if TestControl(myStartButton, tempPt) > 0 then
  1195.                         begin
  1196.                             if TrackControl(myStartButton, tempPt, nil) > 0 then
  1197.                                 begin
  1198.                                     Status := dialing;
  1199.                                     Active := true;
  1200.                                     DrawMainWindow;
  1201.                                 end;
  1202.                         end
  1203.                     else if TestControl(myStopButton, tempPt) > 0 then
  1204.                         begin
  1205.                             if TrackControl(myStopButton, tempPt, nil) > 0 then
  1206.                                 begin
  1207.                                     HangUp;
  1208.                                     Status := idle;
  1209.                                     StartTime := '00:00';
  1210.                                     StopTime := '00:00';
  1211.                                     Active := false;
  1212.                                     DrawMainWindow;
  1213.                                 end;
  1214.                         end;
  1215.                 end;
  1216.             otherwise
  1217.         end;
  1218.     end;
  1219.  
  1220. {------------------------------- Main --------------------------------}
  1221. begin
  1222.     InitialiseVars;
  1223.     if not (SetupMenuBar) then
  1224.         doError(1)
  1225.     else
  1226.         begin
  1227.             if not (SetupWindows) then
  1228.                 doError(2)
  1229.             else
  1230.                 begin
  1231.                     if GetFilename(false) then
  1232.                         begin
  1233.                             SetupDrivers;
  1234.                             DrawMainWindow;
  1235.                             while not (Quit) do
  1236.                                 begin
  1237.                                     if waitNextEvent(everyEvent, myEventRecord, 10, nil) then
  1238.                                         case myEventRecord.what of
  1239.                                             mouseDown: 
  1240.                                                 DoMouseEvent(MyEventRecord);
  1241.                                             updateEvt: 
  1242.                                                 begin
  1243.                                                     BeginUpdate(MainWindow);
  1244.                                                     SetPort(MainWindow);
  1245.                                                     SelectWindow(MainWindow);
  1246.                                                     DrawMainWindow;
  1247.                                                     EndUpdate(MainWindow);
  1248.                                                     SetCursor(Arrow);
  1249.                                                 end;
  1250.                                             keyDown, autoKey: 
  1251.                                                 if BAND(MyEventRecord.modifiers, CmdKey) <> 0 then
  1252.                                                     DoKeyEvent(chr(MyEventRecord.message mod 256));
  1253.                                             otherwise
  1254.                                         end;
  1255.                                     CheckTimer;
  1256.                                     if Active then
  1257.                                         case Status of
  1258.                                             dialing: 
  1259.                                                 DialNumber;
  1260.                                             waiting: 
  1261.                                                 DoSerial;
  1262.                                             otherwise
  1263.                                         end;
  1264.                                 end;
  1265.                             HangUp;
  1266.                             ClearInputBuffer;
  1267.                             CloseDrivers;
  1268.                             CloseResultFile;
  1269.                         end;
  1270.                 end;
  1271.             KillWindows;
  1272.         end;
  1273.     KillMenuBar;
  1274. end.
  1275.  
  1276.  
  1277. {    Well, that's about the size of it!                                                                                 }
  1278. {    now onto the known errors:                                                                                        }
  1279. {    1)    I have problems hanging up the line.  I used to just shutdown the drivers then open them up again    }
  1280. {        This is somewhat bad method I think, but then if it works its fine by me.  I now send +++ followed    }
  1281. {        by a delay then ATH0 (Hayes commands).    This doesn't always work, depending upon the modem.    }
  1282. {        I tried it on a SupraFax modem and it worked, didn't like the Miracom though...try it anyway        }
  1283. {    2)    I also have problems getting things to background properly.  They work and all that but they         }
  1284. {        sometimes halt (least thats what it seems like to me) and when brought to the foreground carry        }
  1285. {        on quite happily.  Maybe I need to check the switches in the SIZE resource.  I have the CAN B'GND    }
  1286. {        switch set and I use waitNextEvent and all that but still things go awry - makes it more fun!            }
  1287. {                                                                                                                        }
  1288. {    Only 2 but they are the most prominent.  This may seem bad (it IS bad) but doesn't always happen        }
  1289. {    Oh yeah, I never support the apple menu properly (da's and stuff).  I just can't me bothered.                }
  1290. {    I know HOW to but I just haven't written the routine - its only a few lines but never got round to it.        }
  1291. {    If you want me to develop this stuff then mail me and I will get it working properly but in the            }
  1292. {    meantime this stuff will suffice.  If nothing else, its worth having for the serial code examples            }
  1293. {                                                                                                                                                            }
  1294. {    ALSO - in the resource file there is a template for hfdr...switch on baloons and point to S&DIII application    }
  1295. {                                                                                                                        }
  1296. {    Lots of Peace, Love and Good Happiness Stuff                                                                    }
  1297. {    Boris                                                                                                                }
  1298. {    BorMak Tech                                                                                                        }
  1299. {    Software and Network Consultants                                                                                }